home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / misc / mf-db.zip / CSAMPLE\CONVERT\MFCONV.C < prev    next >
C/C++ Source or Header  |  1993-09-23  |  6KB  |  250 lines

  1. /*
  2.  
  3.     MF Conversion utility
  4.     Copyright 1993, Carl Brown
  5.     
  6.     Converts MF database types:
  7.         1.0x
  8.         to
  9.         1.02
  10.         
  11.    (compiled under MSC 8.0 (VC++))
  12.  
  13.    You may do whatever you want with this.  It's public domain.
  14.    
  15.    This utility has been placed in a DLL so you can use it
  16.    once and discard (delete) it.
  17.    
  18.    You may distribute this DLL with your application so that
  19.    you can convert end-users systems to the new DB version.
  20.    
  21.    You may also copy this source code and place it in to your own
  22.    source code, if you wish.  (That way the conversion code will
  23.    be embedded into one file...).  Optionally, you may translate this
  24.    code in to another language and embed it in your application(s).
  25.    
  26.    The conversion routines were not placed in the database 
  27.    because they take a while to run and we wouldn't want your
  28.    call to mfOpen to take 1/2 an hour to complete...
  29.    
  30.    This routine also OVER DOUBLES the size of the disk space required
  31.    to hold the DB file.  (only while this routine is running).
  32.    
  33.    ONE LAST WORD:
  34.        BACK UP YOU DATABASE BEFORE RUNNING THIS!
  35.     I tested it on about 200 databases and found a few anomalies along the
  36.     way:
  37.         1- Corrupt databases NEVER convert (they just lock the system...)
  38.         2- Databases with 4 byte records GPF (can't figure out why,,,
  39.             (however, they DO convert!  Wierd...)
  40.  
  41.    -Carl Brown
  42.      
  43.     
  44. */
  45. #include <windows.h>
  46. #include <memory.h>
  47. #include <io.h>
  48.  
  49.  
  50. /*
  51.     External conversion procedure
  52.     
  53.     Call this function with:
  54.         DATABASE (FULL path and filename) to convert
  55.         
  56.         returns:
  57.             0     - All ok
  58.             -1     - Error
  59.       
  60. */
  61. int 
  62.     // this allows it to be a DLL or an EXE...
  63. #ifndef NOT_DLL
  64. FAR PASCAL _export 
  65. #endif
  66. mfConvert(LPSTR lpszDBName)
  67. {
  68.     HFILE    hDBFile;
  69.     HFILE    hTempDBFile;
  70.     
  71.     char    szTempFile[] = "/mfTEMP.$$$";
  72.     
  73.     int        iDBRecSize;        // Internal DB information
  74.     long    lDBNumRecs;
  75.     long    lDBDeletePtr;
  76.     
  77.     
  78.     hDBFile = _lopen(lpszDBName, READ_WRITE);
  79.     if (hDBFile == HFILE_ERROR)
  80.         {
  81.         MessageBox(NULL, "Database could not be opened", "ERROR", MB_OK);
  82.         return (-1);
  83.         }
  84.     
  85.     hTempDBFile = _lcreat((LPSTR)szTempFile, READ_WRITE);
  86.     if (hDBFile == HFILE_ERROR)
  87.         {
  88.         _lclose(hDBFile);
  89.         MessageBox(NULL, "Temporary Database could not be created", "ERROR", MB_OK);
  90.         return (-1);
  91.         }
  92.         
  93.         
  94.     /*
  95.         Read the record size, 
  96.         the # of records in the database, and
  97.         the 'delete' pointer.
  98.     */
  99.      _llseek(hDBFile, 8, SEEK_SET);
  100.      _lread(hDBFile, &iDBRecSize, 2);
  101.  
  102.      _llseek(hDBFile, 14, SEEK_SET);
  103.      _lread(hDBFile, &lDBNumRecs, 4);
  104.  
  105.      _llseek(hDBFile, 18, SEEK_SET);
  106.      _lread(hDBFile, &lDBDeletePtr, 4);
  107.      
  108.      /*
  109.      
  110.          Convert the data to the new DB format
  111.         
  112.      */
  113.          /*
  114.             Fix header information
  115.         */
  116.     {
  117.         char     aHdr[50];
  118.         
  119.         _llseek(hDBFile, 0, SEEK_SET);
  120.         _lread(hDBFile, (LPSTR)aHdr, 50);
  121.         
  122.             /*    Is this a valid MF file?   */
  123.         aHdr[5] = 0;    
  124.         if(lstrcmp((LPSTR)&aHdr, "M1.00") != 0)
  125.             return (-1);
  126.         
  127.         lstrcpy((LPSTR)&aHdr, "M1.02");       
  128.              
  129.            _llseek(hTempDBFile, 0, SEEK_SET);
  130.         _lwrite(hTempDBFile, (LPSTR)aHdr, 50);
  131.         
  132.         _llseek(hTempDBFile, 0, SEEK_SET);
  133.         lstrcpy((LPSTR)&aHdr, "M1.02");
  134.         _lwrite(hTempDBFile, (LPSTR)&aHdr, 5);
  135.         
  136.     
  137.     }      
  138.      
  139.          /*
  140.              Process the old records into the new format
  141.          */
  142.     {
  143.     long    lCurRecord;        // Current record being processed
  144.     
  145.     HGLOBAL    hMemRecord;        // One DB record
  146.     LPSTR    lpRecord;        // "
  147.     
  148.        hMemRecord = GlobalAlloc(GPTR, iDBRecSize + 8);
  149.     lpRecord = GlobalLock(hMemRecord);
  150.      
  151.      /*
  152.          Initialize the last 8 bytes of the new record to 0
  153.         (These are new bytes used by the new file format)
  154.      */
  155.      {
  156.      int n;
  157.      for (n = 1; n <= 8; n++)
  158.          *(lpRecord + iDBRecSize - n) = 0;
  159.      }
  160.      
  161.      for(lCurRecord = 0; lCurRecord <= lDBNumRecs; lCurRecord++)
  162.          {
  163.         _llseek(hDBFile, (lCurRecord * iDBRecSize )  + 50, SEEK_SET);
  164.         _lread(hDBFile, lpRecord, iDBRecSize);
  165.         
  166.         _llseek(hTempDBFile, (lCurRecord * (iDBRecSize + 8))  + 50, SEEK_SET);
  167.         _lwrite(hTempDBFile, lpRecord, iDBRecSize + 8);
  168.      
  169.         }
  170.     GlobalUnlock(hMemRecord);
  171.     GlobalFree(hMemRecord);        
  172.     }
  173.      
  174.      
  175.      /*
  176.          Since the old system contained a linked list of deletes,
  177.         we need to mark all the converted records so the new DB 
  178.         can process deleted records
  179.     */
  180.     {
  181.     int        iDelMarker = 1;
  182.     long    lLiveCount = lDBNumRecs;
  183.     while (lDBDeletePtr != -1)
  184.         {
  185.            _llseek(hTempDBFile, ((lDBDeletePtr + 1) * (iDBRecSize + 8))  + 50 - 8, SEEK_SET);
  186.         _lwrite(hTempDBFile, &iDelMarker, sizeof(int));
  187.         lLiveCount--;
  188.         
  189.         _llseek(hTempDBFile, (lDBDeletePtr * (iDBRecSize + 8))  + 50, SEEK_SET);
  190.         _lread(hTempDBFile, &lDBDeletePtr, sizeof(long));
  191.         
  192.         }
  193.         /*
  194.             Now we know how many live (not deleted) records are
  195.             in the database
  196.         */
  197.     _llseek(hTempDBFile, 22, SEEK_SET);
  198.     _lwrite(hTempDBFile, &lLiveCount, 4);
  199.  
  200.     }
  201.     
  202.     /*
  203.         Now, copy the temp DB over the live DB
  204.     */
  205.     {
  206.     int        bRead;
  207.     static    char ioBuffer[4096];
  208.     _llseek(hTempDBFile, 0, SEEK_SET);
  209.     _llseek(hDBFile, 0, SEEK_SET);
  210.     
  211.     do{
  212.  
  213.         bRead = _lread( hTempDBFile, ioBuffer, 4096 );
  214.         if(bRead == -1)
  215.             return(-1);
  216.  
  217.         if(_lwrite( hDBFile, ioBuffer, bRead ) == -1)
  218.             return(-1);
  219.  
  220.     } while (bRead != 0);
  221.     
  222.     }
  223.     
  224.     _lclose(hDBFile);
  225.     _lclose(hTempDBFile);
  226.     _unlink(szTempFile);
  227.  
  228. }
  229.  
  230.  
  231.  
  232. #ifndef NOT_DLL
  233. /*----------------------------------------------------------------------
  234.    This is required for 'windows' dll's.
  235.    Generally, you put any startup code that you might require,
  236.    initialize variables, allocate memory, etc...
  237. */
  238. int FAR PASCAL LibMain(
  239.         HANDLE  hModule,
  240.         WORD    wDataSeg,
  241.         WORD    cbHeapSize,
  242.         LPSTR   lpszCmdLine
  243.         )
  244. {
  245.    return 1;
  246. }
  247.  
  248. #endif
  249.  
  250.